package com.enation.app.javashop.consumer.shop.message;

import com.enation.app.javashop.consumer.core.event.OrderStatusChangeEvent;
import com.enation.app.javashop.consumer.core.event.RefundStatusChangeEvent;
import com.enation.app.javashop.core.aftersale.model.dos.RefundDO;
import com.enation.app.javashop.core.aftersale.model.enums.RefundStatusEnum;
import com.enation.app.javashop.core.aftersale.model.enums.RefundTypeEnum;
import com.enation.app.javashop.core.base.message.OrderStatusChangeMsg;
import com.enation.app.javashop.core.base.message.RefundChangeMsg;
import com.enation.app.javashop.core.base.rabbitmq.TimeExecute;
import com.enation.app.javashop.core.member.model.dos.ConnectDO;
import com.enation.app.javashop.core.member.model.dos.Member;
import com.enation.app.javashop.core.member.model.enums.ConnectTypeEnum;
import com.enation.app.javashop.core.member.service.ConnectManager;
import com.enation.app.javashop.core.member.service.MemberManager;
import com.enation.app.javashop.core.system.enums.WeChatPublicConstant;
import com.enation.app.javashop.core.system.enums.WechatMiniproTemplateTypeEnum;
import com.enation.app.javashop.core.system.model.dos.WechatMsgTemplate;
import com.enation.app.javashop.core.system.model.dos.WxPublicTemplate;
import com.enation.app.javashop.core.system.model.dos.WxPublicTemplateData;
import com.enation.app.javashop.core.system.model.dto.MiniproMsgDataDTO;
import com.enation.app.javashop.core.system.model.dto.MiniproSendMsgDTO;
import com.enation.app.javashop.core.trade.order.model.dos.OrderDO;
import com.enation.app.javashop.core.trade.order.model.enums.OrderStatusEnum;
import com.enation.app.javashop.core.trade.order.model.vo.OrderSkuVO;
import com.enation.app.javashop.core.trade.order.service.OrderQueryManager;
import com.enation.app.javashop.core.trade.sdk.model.OrderDetailDTO;
import com.enation.app.javashop.framework.database.DaoSupport;
import com.enation.app.javashop.framework.trigger.Interface.TimeTrigger;
import com.enation.app.javashop.framework.util.CurrencyUtil;
import com.enation.app.javashop.framework.util.DateUtil;
import com.enation.app.javashop.framework.util.JsonUtil;
import com.enation.app.javashop.framework.util.StringUtil;
import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 微信发送模板消息（小程序的订阅消息）
 *
 * @author fk
 * @version v7.1.4
 * @since v7.1.4
 * 2019年6月18日 下午3:15:01
 */
@Component
public class WechatMiniproMessageConsumer implements OrderStatusChangeEvent, RefundStatusChangeEvent {

    @Autowired
    private ConnectManager connectManager;
    @Autowired
    private OrderQueryManager orderQueryManager;
    @Autowired
    private TimeTrigger timeTrigger;



    protected final Log logger = LogFactory.getLog(this.getClass());

    // 小程序延迟发送队列前缀名
    private static final String TRIGGER_PREFIX = "MINIPRO_MESSAGE_";


    // 待付款通知延迟发送时间 分钟
    private static final int DELAY_MINUTES = 25;

    /**
     * 订单状态改变
     */
    @Override
    public void orderChange(OrderStatusChangeMsg orderMessage) {
        OrderStatusEnum status = orderMessage.getNewStatus();
        OrderDO orderDO = orderMessage.getOrderDO();
        //商品信息
        String itemsJson = orderDO.getItemsJson();
        List<OrderSkuVO> skuVOList = JsonUtil.jsonToList(itemsJson, OrderSkuVO.class);

        long exeTime = this.getPayNoticeExeTime(orderDO.getCreateTime());

        switch (status) {
            case CONFIRM:
                // sunjian by 2020-11-18
                // this.sendMessage(orderDO, skuVOList, WechatMiniproTemplateTypeEnum.PAY_NOTICE, exeTime);
                break;
            case PAID_OFF:
                // 付款成功删除待付款提醒
                timeTrigger.delete(TimeExecute.MINIPRO_MESSAGE_EXECUTER, exeTime, TRIGGER_PREFIX + orderDO.getTradeSn());
                break;
            case SHIPPED:
                //订单发货提醒
                this.sendMessage(orderDO, skuVOList, WechatMiniproTemplateTypeEnum.SHIP_NOTICE, DateUtil.getDateline());
                break;
            case CANCELLED:
                // 删除待付款提醒
                timeTrigger.delete(TimeExecute.MINIPRO_MESSAGE_EXECUTER, exeTime, TRIGGER_PREFIX + orderDO.getTradeSn());

                // 订单取消发送提醒
                String cancelReason = orderDO.getCancelReason();
                if(cancelReason.contains("超时")){
                    // 未支付自动取消
                    this.sendMessage(orderDO, skuVOList, WechatMiniproTemplateTypeEnum.CANCEL_NOTICE_2, DateUtil.getDateline());
                }else if(cancelReason.contains("商家")){
                    // 运营后台取消
                    this.sendMessage(orderDO, skuVOList, WechatMiniproTemplateTypeEnum.CANCEL_NOTICE_3, DateUtil.getDateline());
                }else{
                    // 主动取消
                    this.sendMessage(orderDO, skuVOList, WechatMiniproTemplateTypeEnum.CANCEL_NOTICE_1, DateUtil.getDateline());
                }
                break;
            default:
        }
    }

    /**
     * 退货退款消息
     */
    @Override
    public void refund(RefundChangeMsg refundChangeMsg) {
        RefundStatusEnum refundStatus = refundChangeMsg.getRefundStatusEnum();
        RefundDO refund = refundChangeMsg.getRefund();
        OrderDetailDTO orderDetailDTO = orderQueryManager.getModel(refund.getOrderSn());
        OrderDO orderDO = orderQueryManager.getModel(orderDetailDTO.getOrderId());
        List<OrderSkuVO> skuVOList = JsonUtil.jsonToList(orderDO.getItemsJson(), OrderSkuVO.class);

        // 设置扩展参数 发送消息时需要用到    refund.getRefuseType() 修改为 refund.getRefundType()  updateTime:2020年9月30日 15:28:24 王志杨
        orderDO.setOrderData(RefundTypeEnum.analysis(refund.getRefundType()));
        // 退货审核通知
        if (RefundStatusEnum.PASS.equals(refundStatus)) {
            this.sendMessage(orderDO, skuVOList, WechatMiniproTemplateTypeEnum.RETUND_NOTICE_1, DateUtil.getDateline());
        }else if(RefundStatusEnum.REFUSE.equals(refundStatus)){
            this.sendMessage(orderDO, skuVOList, WechatMiniproTemplateTypeEnum.RETUND_NOTICE_2, DateUtil.getDateline());
        }
    }


    // 发送消息
    private void sendMessage(OrderDO orderDO, List<OrderSkuVO> skuList, WechatMiniproTemplateTypeEnum templateTypeEnum, Long startTime){
        String tradeSn = orderDO.getTradeSn();
        ConnectDO connect = connectManager.getConnect(orderDO.getMemberId(), ConnectTypeEnum.WECHAT.value());
        if(connect == null){
            logger.warn("小程序消息发送失败，未找到对应的小程序openid");
            return;
        }

        // 封装data参数
        Map<String, Object> dataMap = getDataMap(orderDO, skuList, templateTypeEnum);

        // 封装消息
        MiniproSendMsgDTO miniproSendMsgDTO = new MiniproSendMsgDTO(connect.getOpenId(), templateTypeEnum,
                dataMap, orderDO.getSn());

        // 延迟发送
        timeTrigger.add(TimeExecute.MINIPRO_MESSAGE_EXECUTER, miniproSendMsgDTO , startTime, TRIGGER_PREFIX + tradeSn);
    }


    // 获取数据集合
    private Map<String, Object> getDataMap(OrderDO orderDO, List<OrderSkuVO> skuList, WechatMiniproTemplateTypeEnum templateTypeEnum){
        Map<String, Object> dataMap = new HashMap<>();

        switch (templateTypeEnum){
            case PAY_NOTICE:
                dataMap.put("character_string4", MiniproMsgDataDTO.build(orderDO.getSn()));
                dataMap.put("time5", MiniproMsgDataDTO.build(com.enation.app.javashop.framework.util.DateUtil.toString(orderDO.getCreateTime(), "yyyy-MM-dd HH:mm:ss")));
                dataMap.put("thing3", MiniproMsgDataDTO.build(this.getGoodsName(skuList)));
                dataMap.put("amount1", MiniproMsgDataDTO.build(orderDO.getOrderPrice() + "元"));
                dataMap.put("thing2", MiniproMsgDataDTO.build("你有待支付订单将自动取消，请尽快支付→"));
                break;
            case SHIP_NOTICE:
                dataMap.put("character_string2", MiniproMsgDataDTO.build(orderDO.getSn()));
                dataMap.put("thing1", MiniproMsgDataDTO.build(this.getGoodsName(skuList)));
                dataMap.put("thing4", MiniproMsgDataDTO.build(orderDO.getLogiName())); // 物流公司
                dataMap.put("character_string5", MiniproMsgDataDTO.build(orderDO.getShipNo())); // 物流单号
                dataMap.put("thing10", MiniproMsgDataDTO.build("已全部发货，请留意查收并及时确认收货→"));
                break;
            case CANCEL_NOTICE_1:
                dataMap.put("number7", MiniproMsgDataDTO.build(orderDO.getSn()));
                dataMap.put("thing6", MiniproMsgDataDTO.build(this.getGoodsName(skuList)));
                dataMap.put("date10", MiniproMsgDataDTO.build(com.enation.app.javashop.framework.util.DateUtil.toString(orderDO.getCreateTime(), "yyyy-MM-dd HH:mm:ss"))); // 下单时间
                dataMap.put("thing1", MiniproMsgDataDTO.build("用户主动取消")); // 取消原因
                dataMap.put("thing4", MiniproMsgDataDTO.build("订单已取消，已付款项7日内退回，请留意→"));
                break;
            case CANCEL_NOTICE_2:
                dataMap.put("number7", MiniproMsgDataDTO.build(orderDO.getSn()));
                dataMap.put("thing6", MiniproMsgDataDTO.build(this.getGoodsName(skuList)));
                dataMap.put("date10", MiniproMsgDataDTO.build(com.enation.app.javashop.framework.util.DateUtil.toString(orderDO.getCreateTime(), "yyyy-MM-dd HH:mm:ss"))); // 下单时间
                dataMap.put("thing1", MiniproMsgDataDTO.build("订单超时未支付，自动取消")); // 取消原因
                dataMap.put("thing4", MiniproMsgDataDTO.build("订单超时未支付已自动取消，请知悉→"));
                break;
            case CANCEL_NOTICE_3:
                dataMap.put("number7", MiniproMsgDataDTO.build(orderDO.getSn()));
                dataMap.put("thing6", MiniproMsgDataDTO.build(this.getGoodsName(skuList)));
                dataMap.put("date10", MiniproMsgDataDTO.build(com.enation.app.javashop.framework.util.DateUtil.toString(orderDO.getCreateTime(), "yyyy-MM-dd HH:mm:ss"))); // 下单时间
                dataMap.put("thing1", MiniproMsgDataDTO.build("商家取消订单")); // 取消原因
                dataMap.put("thing4", MiniproMsgDataDTO.build("订单已取消，已付款项7日内退回，请留意→"));
                break;
            case RETUND_NOTICE_1:
                dataMap.put("character_string1", MiniproMsgDataDTO.build(orderDO.getSn()));
                dataMap.put("thing6", MiniproMsgDataDTO.build(this.getGoodsName(skuList)));
                dataMap.put("phrase2", MiniproMsgDataDTO.build(orderDO.getOrderData()));  // 售后类型
                dataMap.put("phrase3", MiniproMsgDataDTO.build("审核通过")); // 售后状态
                dataMap.put("thing5", MiniproMsgDataDTO.build("商家已同意您的售后申请，点击查看详情→"));
                break;
            case RETUND_NOTICE_2:
                dataMap.put("character_string1", MiniproMsgDataDTO.build(orderDO.getSn()));
                dataMap.put("thing6", MiniproMsgDataDTO.build(this.getGoodsName(skuList)));
                dataMap.put("phrase2", MiniproMsgDataDTO.build(orderDO.getOrderData())); // 售后类型
                dataMap.put("phrase3", MiniproMsgDataDTO.build("审核拒绝")); // 售后状态
                dataMap.put("thing5", MiniproMsgDataDTO.build("商家拒绝了您的售后申请，点击查看详情→"));
                break;
            default:
                break;
        }
        return dataMap;
    }

    // 获取订单商品名称
    private String getGoodsName(List<OrderSkuVO> skuList){
        OrderSkuVO orderSkuVO = skuList.get(0);
        String goodsName = orderSkuVO.getName();
        if(goodsName.length() >= 20){
            goodsName = goodsName.substring(0, 17) + "...";
        }
        return goodsName;
    }


    /**
     * 计算支付通知提醒执行时间
     */
    private long getPayNoticeExeTime(long createTime){
        Date exeTime = DateUtils.addMinutes(new Date(createTime * 1000), DELAY_MINUTES);
        return exeTime.getTime() / 1000;
    }
}
